<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2017/11/8
 * Time: 11:32
 */

namespace Home\Controller;


use Think\Controller;

/**
 * Class WeiXinPayJsController
 * @package Home\Controller
 * @User: yfl
 * @Time: 2017年11月8日 11:24:33
 * @description:H5支付是指商户在微信客户端外的移动端网页展示商品或服务，用户在前述页面确认使用微信支付时，商户发起本服务呼起微信客户端进行支付。
 * 主要用于触屏版的手机浏览器请求微信支付的场景。可以方便的从外部浏览器唤起微信支付
 */
class WeiXinPayJsController extends Controller
{
    protected $redirect_uri = 'http://m.1615.cn/login/pay/payinfo'; //回调地址

    protected $app_id = 'wxe97ef921fd60d98c';//微信分配的公众账号ID

    protected $mch_id = '1462775702';//微信支付分配的商户号

    protected $key = '99999999';//自己设置的微信商家key

    protected $trade_type = 'MWEB';//交易类型 具体看API 里面有详细介绍

    protected $rand;

    protected $out_trade_no;

    public function __construct()
    {
        parent::__construct();
//        $res = vendor('WeixinPayJs.WxPay#JsApiPay');
//        dump($res);
    }

    public function index()
    {
        $money = htmlspecialchars(I('post.money', '100', 'invtal'), ENT_QUOTES);//充值金额

        $money = is_numeric($money) ? $money : $money;

        $body=htmlspecialchars(I('post.money', ''), ENT_QUOTES);

        $body=!empty($body)?$body:'H5充值';//商品简单描述

        $appid = $this->app_id;

        $mch_id = $this->mch_id;

        $key = $this->key;//自己设置的微信商家key

        $rand = mt_rand(00000, 99999);

        $out_trade_no = time() . $rand;//平台内部订单号

        $nonce_str = MD5($out_trade_no);//随机字符串

        $total_fee = $money; //金额

        $userIp = $this->get_client_ip(); //获得用户设备IP

        $spbill_create_ip = $userIp; //IP

//        $notify_url = "http://www.baidu.com/login/pay/payinfo"; //回调地址

        $notify_url = $this->redirect_uri; //回调地址

        $trade_type = $this->trade_type;//交易类型 具体看API 里面有详细介绍

        $scene_info = '{"h5_info":{"type":"Wap","wap_url":"http://www.baidu.com","wap_name":"支付"}}';//场景信息 必要参数

        //对参数按照key=value的格式，并按照参数名ASCII字典序排序生成字符串

        $signA = "appid=$appid&body=$body&mch_id=$mch_id&nonce_str=$nonce_str&notify_url=$notify_url&out_trade_no=$out_trade_no&scene_info=$scene_info&spbill_create_ip=$spbill_create_ip&total_fee=$total_fee&trade_type=$trade_type";

        $strSignTmp = $signA . "&key=$key"; //拼接字符串  注意顺序微信有个测试网址 顺序按照他的来 直接点下面的校正测试 包括下面XML  是否正确

        $sign = strtoupper(MD5($strSignTmp)); // MD5 后转换成大写

        /**
         * appid 微信分配的公众账号ID
         * mch_id 微信支付分配的商户号
         * nonce_str 随机字符串，不长于32位
         * sign 签名
         * body 商品描述
         * out_trade_no 商户订单号
         * total_fee 总金额
         * spbill_create_ip 终端IP
         * notify_url 接收微信支付异步通知回调地址，通知url必须为直接可访问的url，不能携带参数。
         * trade_type 交易类型
         * scene_info 场景信息
         */
        $post_data = "<xml>  
                       <appid>$appid</appid>  
                       <body>$body</body>  
                       <mch_id>$mch_id</mch_id>  
                       <nonce_str>$nonce_str</nonce_str>  
                       <notify_url>$notify_url</notify_url>  
                       <out_trade_no>$out_trade_no</out_trade_no>  
                       <scene_info>$scene_info</scene_info>  
                       <spbill_create_ip>$spbill_create_ip</spbill_create_ip>  
                       <total_fee>$total_fee</total_fee>  
                       <trade_type>$trade_type</trade_type>  
                       <sign>$sign</sign>  
                   </xml>";//拼接成XML 格式

        $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";//微信传参地址

        $dataxml = $this->http_post($url, $post_data); //后台POST微信传参地址  同时取得微信返回的参数    POST 方法我写下面了

        $objectxml = (array)simplexml_load_string($dataxml, 'SimpleXMLElement', LIBXML_NOCDATA); //将微信返回的XML 转换成数组

//        dump($objectxml);
        if ($objectxml['return_code'] == 'SUCCESS') {

            if ($objectxml['result_code'] == 'SUCCESS') {//如果这两个都为此状态则返回mweb_url，详情看‘统一下单’接口文档
                return $objectxml['mweb_url']; //mweb_url是微信返回的支付连接要把这个连接分配到前台
            }
            if ($objectxml['result_code'] == 'FAIL') {
                return $err_code_des = $objectxml['return_msg'];

            }
        }
    }

    /**
     * @User: yfl
     * @Time: 2017年11月8日 18:39:34
     * @description:验证签名
     */
    private function verifySign()
    {

    }
    /**
     * @param $url
     * @param $data
     * @return mixed
     * @User: yfl
     * @Time: 2017年11月8日 15:24:41
     * @description: curl 请求数据
     */
    protected function http_post($url, $data)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        $res = curl_exec($ch);
        curl_close($ch);
        return $res;
    }

    /**
     * @return string
     * @User: yfl
     * @Time: 2017年11月8日 15:24:15
     * @description:在写微信H5支付的时候需要获取终端IP使用官方的方法是不对的
     */
    protected function get_client_ip()
    {
        if (getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {

            $ip = getenv('HTTP_CLIENT_IP');

        } elseif (getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {

            $ip = getenv('HTTP_X_FORWARDED_FOR');

        } elseif (getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {

            $ip = getenv('REMOTE_ADDR');

        } elseif (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {

            $ip = $_SERVER['REMOTE_ADDR'];

        }
        return preg_match('/[\d\.]{7,15}/', $ip, $matches) ? $matches [0] : '';
    }
}
